package com.ehotting.edsta.system.service.impl;

import java.text.SimpleDateFormat;
import java.util.*;

import com.alibaba.fastjson.JSON;
import com.ehotting.eaf.core.domain.csharpServer.LicenseSignedDto;
import com.ehotting.eaf.core.domain.system.api.SysDictData;
import com.ehotting.eaf.core.domain.system.api.SysUser;
import com.ehotting.eaf.core.domain.system.api.UserLicense;
import com.ehotting.eaf.core.domain.system.api.UserRsa;
import com.ehotting.eaf.core.enums.LicenseStatus;
import com.ehotting.eaf.core.exception.ServiceException;
import com.ehotting.eaf.core.utils.AesUtils;
import com.ehotting.eaf.core.utils.DateUtils;
import com.ehotting.eaf.core.utils.HexUtils;
import com.ehotting.eaf.core.utils.RsaUtils;
import com.ehotting.eaf.security.service.SendSmsService;
import com.ehotting.edsta.system.config.SmsConfig;
import com.ehotting.edsta.system.mapper.SysUserMapper;
import com.ehotting.edsta.system.mapper.UserLicenseMapper;
import com.ehotting.edsta.system.mapper.UserRsaMapper;
import com.ehotting.edsta.system.service.ISysDictDataService;
import com.ehotting.edsta.system.service.IUserLicenseService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * C端用户licenseService业务层处理
 * 
 * @author edsta
 * @date 2023-03-24
 */
@Slf4j
@Service
public class UserLicenseServiceImpl implements IUserLicenseService
{
    @Autowired
    private UserLicenseMapper userLicenseMapper;

    @Autowired
    private SendSmsService sendSmsService;

    @Autowired
    private SmsConfig smsConfig;

    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private ISysDictDataService dataService;

    @Autowired
    private UserRsaMapper userRsaMapper;

    @Value("${aes.password}")
    private String aesPwd;
    /**
     * 查询C端用户license
     * 
     * @param id C端用户license主键
     * @return C端用户license
     */
    @Override
    public UserLicense selectUserLicenseById(Long id)
    {
        return userLicenseMapper.selectUserLicenseById(id);
    }

    /**
     * 查询C端用户license列表
     * 
     * @param userLicense C端用户license
     * @return C端用户license
     */
    @Override
    public List<UserLicense> selectUserLicenseList(UserLicense userLicense)
    {
        return userLicenseMapper.selectUserLicenseList(userLicense);
    }

    /**
     * 新增C端用户license
     * 
     * @param userLicense C端用户license
     * @return 结果
     */
    @Override
    public int insertUserLicense(UserLicense userLicense)
    {
        return userLicenseMapper.insertUserLicense(userLicense);
    }

    /**
     * 修改C端用户license
     * 
     * @param userLicense C端用户license
     * @return 结果
     */
    @Override
    public int updateUserLicense(UserLicense userLicense)
    {
        return userLicenseMapper.updateUserLicense(userLicense);
    }

    /**
     * 批量删除C端用户license
     * 
     * @param ids 需要删除的C端用户license主键
     * @return 结果
     */
    @Override
    public int deleteUserLicenseByIds(Long[] ids)
    {
        return userLicenseMapper.deleteUserLicenseByIds(ids);
    }

    /**
     * 删除C端用户license信息
     * 
     * @param id C端用户license主键
     * @return 结果
     */
    @Override
    public int deleteUserLicenseById(Long id)
    {
        return userLicenseMapper.deleteUserLicenseById(id);
    }

    /**
     * 批量审核
     * @param ids
     * @param status
     * @return
     */
    @Transactional
    @Override
    public int verifyUserLicenseByIds(Long[] ids, String status) {
        for (Long id : ids) {
            UserLicense userLicense = userLicenseMapper.selectUserLicenseById(id);
            sendVerifySms(id,userLicense);
        }
        return userLicenseMapper.verifyUserLicenseByIds(ids,status);
    }

    /**
     * 审核通过license
     * @param id
     * @return
     */
    @Transactional
    @Override
    public int verifyUserLicenseById(Long id) {
        int result = userLicenseMapper.verifyUserLicenseById(id,LicenseStatus.NORMAL.getCode());
        UserLicense userLicense = userLicenseMapper.selectUserLicenseById(id);
        if (result > 0) {
            sendVerifySms(id,userLicense);
        }
        return result;
    }

    /**
     * 审核通过续费license
     * @param id
     * @return
     */
    @Transactional
    @Override
    public int verifyExtendUserLicenseById(Long id) {
        UserLicense userLicense = userLicenseMapper.selectUserLicenseById(id);
        UserLicense updateLicense = new UserLicense();
        updateLicense.setId(userLicense.getId());

        updateLicense.setExpireTime(userLicense.getExtendTime());
        updateLicense.setStatus(LicenseStatus.NORMAL.getCode());

        resignLicense(userLicense, updateLicense);

        int result = userLicenseMapper.updateUserLicense(updateLicense);
        if (result > 0) {

            userLicense.setExpireTime(userLicense.getExtendTime());
            sendVerifySms(id,userLicense);
        }
        return result;
    }

    private void resignLicense(UserLicense userLicense, UserLicense updateLicense) {
        // 重新签名
        LicenseSignedDto licenseSignedDto = JSON.parseObject(userLicense.getLicense(), LicenseSignedDto.class);
        licenseSignedDto.setExpiredTimeStr(DateUtils.daFormat(userLicense.getExtendTime()));
        UserRsa userRsa = userRsaMapper.selectUserRsaByUserId(userLicense.getUserId());
        try {
            // 使用rsa私钥对license内容签名
            String sign = RsaUtils.sign(userRsa.getRsaPrivateKey(), licenseSignedDto.toString());
            // 使用aes密钥对签名进行加密
            String encrypt = AesUtils.encrypt(aesPwd, sign);
            licenseSignedDto.setSign(encrypt);
        } catch (Exception e) {
            throw new ServiceException("RSA签名失败，请联系管理人员");
        }
        updateLicense.setLicense(JSON.toJSONString(licenseSignedDto));
    }


    @Transactional
    @Override
    public int cancelUserLicenseById(Long id) {
        return userLicenseMapper.verifyUserLicenseById(id,LicenseStatus.EXPIRED.getCode());
    }

    /**
     * 发送审批通过短信
     * @param id
     */
    private void sendVerifySms(Long id,UserLicense userLicense) {
        log.info("send sms>>");
        String[] dbFeatureNames = getDbFeatureNames();


        SysUser sysUser = userMapper.selectUserById(userLicense.getUserId());

        String phonenumber = userLicense.getPhonenumber();
        String enterpriseName = userLicense.getEnterpriseName();
        Map<String, String> map = new HashMap<>();
        map.put("1",sysUser.getUserName());
        String featureName = userLicense.getFeatureName();
        String[] split = featureName.split(",");


        String hexStr = generateCode(dbFeatureNames, split);

        map.put("2", hexStr);
        Date expireTime = userLicense.getExpireTime();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy年MM月dd日");
        String dateString = formatter.format(expireTime);

        map.put("3",dateString);

        boolean b = sendSmsService.sendSMS(smsConfig.getSms_544012(), map, phonenumber);

        if(!b){
            throw new ServiceException("["+phonenumber+"]短信发送失败");
        }

        log.info("sms send successful.");
    }

    private String generateCode(String[] dbFeatureNames, String[] selectedModules) {
        int[] result = new int[8]; // 生成一个长度为8的结果数组

        for (int i = 0; i < dbFeatureNames.length; i++) {
            // 将未在selectedModules中出现的模块设置为0，在selectedModules中出现的模块设置为1
            result[i] = (Arrays.binarySearch(selectedModules, dbFeatureNames[i]) < 0) ? 0 : 1;
        }
        // 比如选择了driver_adapt pcb_modeling simulation circuit_design diagnosis_predict这几个模块
        // result的数组就为[1, 0, 0, 0, 1, 0, 1, 0]，认为是两个字节：10001010
        // 再转为十六进制字符串，这个十六进制字符串就是短信中显示授权类型

        StringBuilder sb = new StringBuilder();
        for (int i : result) {
            sb.append(Integer.toHexString(i));
        }
        return HexUtils.binStr2HexStr(sb.toString());
    }

    private String[] getDbFeatureNames() {
        SysDictData sysDictData = new SysDictData();
        sysDictData.setDictType("feature_name");
        List<SysDictData> sysDictDataList = dataService.selectDictDataList(sysDictData);

        List<String> dbFeatureNameList = new ArrayList<>(sysDictDataList.size());
        String[] dbFeatureNames = new String[sysDictDataList.size()];
        for (SysDictData dictData : sysDictDataList) {
            dbFeatureNameList.add(dictData.getDictValue());
        }
        dbFeatureNameList.toArray(dbFeatureNames);

        return dbFeatureNames;
    }
}
